#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <mutex>
#include <atomic>
#include <cassert>

namespace cl{
#define BUFFER_DEFAULT_SIZE (1*1024*1024)       // 默认大小 1MB
#define BUFFER_INCREMENT_SIZE (1*1024*1024)     // 每次增大 1MB
#define BUFFER_THRESHOLD_SIZE (10*1024*1024)    // 阈值大小 10MB
/**
 * @brief 缓冲区类，用于管理动态大小的缓冲区，支持数据的读写和扩展。
 * 
 * 该类实现了一个支持自动扩展的缓冲区，用于高效地管理数据的读写操作。
 * 通过确保缓冲区在写入时有足够的空间，避免了频繁的内存分配操作，从而提高了性能。
 * 主要功能包括检查缓冲区是否为空，获取可读/可写数据的大小，以及数据的读写操作。
 * 
 * @note 当写入的数据超出当前可写空间时，缓冲区会自动进行扩展。
 */
class Buffer{
public:
    // 构造函数，初始化读写索引和缓冲区大小
    Buffer(): _reader_idx(0), _writer_idx(0), _v(BUFFER_DEFAULT_SIZE){}
    
    // 检查缓冲区是否为空
    bool empty() const { return _reader_idx == _writer_idx; }

    // 获取可读/可写数据的大小
    size_t readAbleSize() const { return _writer_idx - _reader_idx; }
    size_t writeAbleSize() const { return _v.size() - _writer_idx; }
    
    // 重置缓冲区的读写索引
    void reset() { _reader_idx = _writer_idx = 0; }

    // 交换当前缓冲区与另一个缓冲区的内容
    void swap(Buffer &buf){
        _v.swap(buf._v);
        std::swap(_reader_idx, buf._reader_idx);
        std::swap(_writer_idx, buf._writer_idx);
    }

    // 向缓冲区写入数据
    void push(const char* data, size_t len){
        assert(len <= writeAbleSize()); // 确保写入长度不超过可写大小
        ensureEnoughSpace(len);         // 确保有足够的空间
        std::copy(data, data+len, &_v[_writer_idx]);    // 拷贝数据
        _writer_idx += len;             // 更新索引
    }

    // 获取当前可读数据的开始地址
    const char* begin() const { return &_v[_writer_idx]; }

    // 从缓冲区弹出数据
    void pop(size_t len){
        _reader_idx += len;
        assert(_reader_idx <= _writer_idx);
    }

protected:
    // 确保缓冲区有足够的空间来写入数据
    void ensureEnoughSpace(size_t len){
        if(len <= writeAbleSize()) return;

        // 每次增大 1MB 大小
        size_t new_capacity;
        if(_v.size() < BUFFER_THRESHOLD_SIZE)
            new_capacity = _v.size() * 2 + len;
        else
            new_capacity = _v.size() + BUFFER_INCREMENT_SIZE + len;
        _v.resize(new_capacity);
    }

private:
    size_t _reader_idx;     // 读索引
    size_t _writer_idx;     // 写索引
    std::vector<char> _v;   // 缓冲区数据
}; // class Buffer
}